/*
 * Copyright (c) 2008, Takashi Ito
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the authors nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _TANSU_UPNP_CP_H_
#define _TANSU_UPNP_CP_H_

#include "tansu_status.h"
#include "tansu_util.h"
#include "tansu_ssdp.h"
#include "tdom.h"


struct tansu_cp_device;

struct tansu_cp_service {
    STAILQ_ENTRY(tansu_cp_service) next;
    char *type;
    char *sid;
    struct tdom_doc *scpd;
    time_t timestamp;
    struct event exp_ev;
};

STAILQ_HEAD(tansu_cp_devices, tansu_cp_device);
STAILQ_HEAD(tansu_cp_services, tansu_cp_service);

struct tansu_cp_device {
    STAILQ_ENTRY(tansu_cp_device) next;
    const char *udn;
    char *location;
    struct tdom_doc *dd;
    struct tdom_elem *rootdevice;
    struct tdom_elem *embedded;
    struct tansu_cp_services services;
    time_t timestamp;
    struct event exp_ev;
};

enum tansu_ssdp_state {
    TANSU_SSDP_STATE_CREATED = 0,
#if 0
    TANSU_SSDP_STATE_ACTIVE,
    TANSU_SSDP_STATE_FAILED,
    TANSU_SSDP_STATE_FORBIDDEN,
    TANSU_SSDP_STATE_INVALID,
#endif
    TANSU_SSDP_STATE_ONLINE,
    TANSU_SSDP_STATE_OFFLINE,
};

struct tansu_cp_discovery {
    STAILQ_ENTRY(tansu_cp_discovery) next;
    char *udn;
    const char *location;
    struct evhttp_connection *conn;
    struct tansu_ssdp_packet *packet;
    time_t timestamp;
    enum tansu_ssdp_state state;
    int last_status;
    int jobs;
};

STAILQ_HEAD(tansu_cp_discoveries, tansu_cp_discovery);

#ifdef __cplusplus
extern "C" {
#endif

struct tansu_cp_discovery *
tansu_cp_discovery_new(struct event_base *evbase,
                       const char *udn,
                       const struct tansu_ssdp_packet *packet);

void
tansu_cp_discovery_delete(struct tansu_cp_discovery *discovery);

tansu_status_t
tansu_http_get(struct evhttp_connection *conn,
               const char *path,
               struct evkeyvalq *headers,
               void cb(struct evhttp_request *, void *),
               void *cbarg);

tansu_status_t
tansu_http_request(struct evhttp_connection *conn,
                   const char *method,
                   const char *path,
                   void cb(struct evhttp_request *, void *),
                   void *cbarg,
                   struct evhttp_request **req);

struct tansu_cp_discovery *
tansu_cp_discoveries_get(struct tansu_cp_discoveries *list, const char *udn);

struct tansu_cp_service *
tansu_cp_service_new(const char *type, const char *sid, struct tdom_doc *scpd);
void tansu_cp_service_delete(struct tansu_cp_service *service);

struct tansu_cp_device *tansu_cp_device_new(const char *udn,
                                            const char *location,
                                            struct tdom_doc *doc);
void tansu_cp_device_delete(struct tansu_cp_device *device);

char *tansu_url_get_abs(const char *location, const char *base, const char *relative);

struct tdom_doc *tansu_xml_parse(const char *buff, int buffsize);

struct evkeyvalq *tansu_evkeyvalq_clone(const struct evkeyvalq *keyvals);

#define tansu_xml_parse_evbuffer(buffer) \
    tansu_xml_parse((char *)EVBUFFER_DATA((buffer)), EVBUFFER_LENGTH((buffer)))

#ifdef __cplusplus
}
#endif

#endif /* _TANSU_UPNP_CP_H_ */

